package de.hochschuletrier.bachelor.antfarm.entity;

import java.awt.Point;
import java.util.ArrayList;
import java.util.List;

import org.newdawn.slick.GameContainer;

import de.hochschuletrier.bachelor.antfarm.entity.ant.Antstate;
import de.hochschuletrier.bachelor.antfarm.entity.ant.Collectstate;
import de.hochschuletrier.bachelor.antfarm.entity.ant.Returnstate;
import de.hochschuletrier.bachelor.antfarm.entity.ant.Searchstate;
import de.hochschuletrier.bachelor.antfarm.settings.Settings;
import de.hochschuletrier.bachelor.antfarm.util.AssetManager;
import de.hochschuletrier.bachelor.antfarm.util.DistanceHelper;
import de.hochschuletrier.bachelor.antfarm.util.assets.AssetImage;
import de.hochschuletrier.bachelor.antfarm.world.Map;
import de.hochschuletrier.bachelor.antfarm.world.World;

public class Ant extends Entity {
	private Antstate state;
	private Foodpiece piece;
	private Nest nest;
	private ArrayList<Point> lastPositions;

	public Ant(Nest nest) {
		super("Ameise", nest.getX(), nest.getY(), AssetManager.getInstance().getImage(AssetImage.ant));

		this.nest = nest;
		lastPositions = new ArrayList<Point>();
	}

	public Nest getNest() {
		return nest;
	}

	public boolean isFoodsourceNearby() {
		Foodsource nearestSource = getNextFoodsource();
		if (nearestSource == null) {
			return false;
		}
		float dist = DistanceHelper.getDistance(this, nearestSource);
		return dist <= Settings.getSeeDistanceToNest();
	}

	public Foodsource getNextFoodsource() {
		List<Foodsource> list = World.getInstance().getFoodsources();
		float dist = 0f;
		Foodsource nearestSource = null;
		for (Foodsource s : list) {
			float currentDist = DistanceHelper.getDistance(this,s);
			if (dist == 0 || currentDist < dist) {
				dist = currentDist;
				nearestSource = s;
			}
		}
		return nearestSource;
	}

	public void walkTo(int x, int y) {
		Map map = World.getInstance().getMap();
		if (x < 0 || y < 0 || x >= map.getWidth() || y >= map.getHeight()) {
			throw new IllegalArgumentException("Ungültige Koordinaten angeben!");
		}
		if (getX() != x || getY() != y) {
			setX(x);
			setY(y);
			if (getState() != null && getState() instanceof Returnstate) {
				addReturningPheromon(getX(), getY());
			}
			else {
				addPheromon(getX(), getY());
			}
			addPosition(x,y);
		}
	}

	private void addPheromon(int x, int y) {
		World.getInstance().putPheromon(x, y);
	}

	private void addReturningPheromon(int x, int y) {
		World.getInstance().putPheromon(x, y);
		World.getInstance().putPheromon(x, y);
		World.getInstance().putPheromon(x, y);
		
		World.getInstance().putPheromon(x-1, y);
		World.getInstance().putPheromon(x, y-1);
		World.getInstance().putPheromon(x+1, y);
		World.getInstance().putPheromon(x, y+1);
	}

	@Override
	public void update(GameContainer gc, int delta) {
		/*int randX = ((int) (Math.random() * 3)) - 1;
		int randY = ((int) (Math.random() * 3)) - 1;
		int direction = Direction.getDirection(randX, randY);
		if (direction != -1 && direction != lastDirection) {
			walkTo(getX() + randX, getY() + randY);
			lastDirection = Direction.getDirection(randX, randY);
		}*/
		if (getState() == null) {
			switch (nest.getTaskForAnt()) {
			case collecting:
				setState(new Collectstate());
				break;
			case scouting:
				setState(new Searchstate(this));
				break;
			}
		}
		state.perform(this);
	}

	public Antstate getState() {
		return state;
	}
	
	public void setState(Antstate state) {
		if (this.state != null) {
			if (this.state instanceof Searchstate) {
				nest.setScoutingAnts(nest.getScoutingAnts() - 1);
			}
			else if (this.state instanceof Searchstate) {
				nest.setCollectingAnts(nest.getCollectingAnts() - 1);
			}
		}
		this.state = state;
	}

	public Foodpiece getFoodpiece() {
		return piece;
	}

	public void setFoodpiece(Foodpiece piece) {
		this.piece = piece;
		if (piece != null) {
			setImage(AssetManager.getInstance().getImage(AssetImage.ant_with_food));
		}
	}

	public ArrayList<Point> getLastPositions() {
		return lastPositions;
	}

	public void addPosition(Point p) {
		lastPositions.add(p);
//		if (lastPositions.size() > Settings.getMaxPositions()) {
//			lastPositions.remove(0);
//		}
	}
	
	public void addPosition(int x, int y) {
		addPosition(new Point(x,y));
	}
}
